package me.kagami.fup;

import com.alibaba.excel.EasyExcel;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.*;
import com.intellij.util.IncorrectOperationException;
import me.kagami.fup.excel.ExportData;
import org.apache.commons.httpclient.util.DateUtil;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class FindUsagesIntentionAction extends PsiElementBaseIntentionAction {
    @Override
    public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
        PsiElement psiParent = PsiTreeUtil.getParentOfType(element, PsiField.class);
        PsiElement psiParent1 = PsiTreeUtil.getParentOfType(element, PsiClass.class);
        if (psiParent instanceof PsiField) {
            handleField(project, psiParent);
        } else {
            handleClass(project, psiParent1);
        }


    }

    private void handleClass(@NotNull Project project, PsiElement psiParent1) {
        if (psiParent1 instanceof PsiClass) {
            PsiClass psiClass = (PsiClass) psiParent1;
            PsiField[] allFields = psiClass.getAllFields();
            List<ExportData> result = new ArrayList<>();

            ApplicationManager.getApplication().runWriteAction(() -> {
                for (PsiField field : allFields) {
                    FindUsagesPlusHandler findUsagesPlusHandler = new FindUsagesPlusHandler(project);
                    findUsagesPlusHandler.doHandle(field);
                    ResultCollector resultCollector = findUsagesPlusHandler.getResultCollector();
                    resultCollector.printSelf();
                    result.addAll(resultCollector.toExportDataList());
                }
                EasyExcel.write(project.getBasePath() + "/" + DateUtil.formatDate(new Date(), "yyyyMMdd") + ".xlsx", ExportData.class).sheet().doWrite(result);
            });


        }

    }

    private void handleField(@NotNull Project project, PsiElement psiParent) {
        if (psiParent instanceof PsiField) {
            PsiField psiField = (PsiField) psiParent;

            ApplicationManager.getApplication().runWriteAction(() -> {
                FindUsagesPlusHandler findUsagesPlusHandler = new FindUsagesPlusHandler(project);
                findUsagesPlusHandler.doHandle(psiField);
                ResultCollector resultCollector = findUsagesPlusHandler.getResultCollector();
                resultCollector.printSelf();
                List<ResultCollector.ResultBean> resultBeans = resultCollector.getResultBeans();
                if (resultBeans.size() == 0) {
                    return;
                }

                UsageViewManager usageViewManager = UsageViewManager.getInstance(project);
                UsageViewPresentation usageViewPresentation = new UsageViewPresentation();
                usageViewPresentation.setTargetsNodeText("涉及到的类");
                usageViewPresentation.setCodeUsagesString("追踪到的引用");
                usageViewPresentation.setTabText("Find Usage Plus");

                UsageTarget[] usageTargets = {new PsiElement2UsageTargetAdapter(resultBeans.get(0).getField().getContainingClass())};

                int count = (int) resultBeans.stream().filter(p -> p.getPsiElement() != null).count();
                PsiElement[] primaryElements = new PsiElement[count];
                UsageInfo[] usageInfo = new UsageInfo[count];
                for (int i = 0; i < resultBeans.size(); i++) {
                    ResultCollector.ResultBean resultBean = resultBeans.get(i);
                    if (resultBean.getPsiElement() == null) {
                        continue;
                    }
                    primaryElements[i] = resultBean.getPsiElement();
                    usageInfo[i] = new UsageInfo(resultBean.getPsiElement());
                }
                if (primaryElements.length == 0) {
                    UsageViewManager.getInstance(project).showUsages(UsageTarget.EMPTY_ARRAY, new Usage[]{}, usageViewPresentation);
                } else {
                    Usage[] convert = UsageInfoToUsageConverter.convert(primaryElements, usageInfo);
                    usageViewManager.showUsages(usageTargets, convert, usageViewPresentation);
                }

            });


        }
    }

    @Override
    public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement psiElement) {
        PsiElement psiField = PsiTreeUtil.getParentOfType(psiElement, PsiField.class);
        PsiElement psiClass = PsiTreeUtil.getParentOfType(psiElement, PsiClass.class);
        if (psiField != null) {
            return true;
        }
        if (psiClass != null) {
            if (psiElement.getParent() instanceof PsiClass) {
                return true;
            }
            return false;
        }

        return false;
    }

    @Override
    public @NotNull
    String getFamilyName() {
        return "find usage plus";
    }

    @Override
    public @NotNull
    String getText() {
        return "find usage plus";
    }

}
